/**
 * agGrid控件
 *
 * @class IBizDataGridPro
 * @extends {IBizDataGrid}
 */
class IBizDataGrid2 extends IBizDataGrid {
    /**
     * agGrid控件api对象
     *
     * @type {*}
     * @memberof IBizDataGridPro
     */
    public agGridApi: any = null;

    /**
     * agGrid列api对象
     *
     * @type {*}
     * @memberof IBizDataGrid2
     */
    public agGridColumnApi: any = null;

    /**
     * agGrid列数组
     *
     * @type {Array<any>}
     * @memberof IBizDataGrid2
     */
    public columnDefs: Array<any> = [];

    /**
     * 树表格列模型
     *
     * @type {*}
     * @memberof IBizDataGrid2
     */
    public treeColMode: any = {};

    /**
     * 自定义分组列
     *
     * @type {*}
     * @memberof IBizDataGrid2
     */
    public autoGroupColumn: any = null;

    /**
     * 列过滤参数
     *
     * @type {*}
     * @memberof IBizDataGrid2
     */
    public colFilterParams: any = {};

    /**
     * 是否开启列过滤
     *
     * @type {boolean}
     * @memberof IBizDataGrid2
     */
    public isOpenFilter: boolean = false;

    /**
     *Creates an instance of IBizDataGrid2.
     * @param {*} [opts={}]
     * @memberof IBizDataGrid2
     */
    constructor(opts: any = {}) {
        super(opts);
        if(Object.is(this.getGridStyle(), 'TREEGRID')) {
            this.setTreeColMode();
        }
        this.setIsOpenFilter();
        this.regColumnDefs();
        if(!this.autoGroupColumn) {
            this.setCheckboxColumn();
        }
    }

    /**
     * 加载数据
     *
     * @param {*} [arg={}]
     * @returns {void}
     * @memberof IBizGrid
     */
    public load(arg: any = {}): void {
        // tslint:disable-next-line:prefer-const
        let opt: any = {};
        Object.assign(opt, arg);
        Object.assign(opt, { srfctrlid: this.getName(), srfaction: 'fetch' });
        if (!opt.start) {
            Object.assign(opt, { start: (this.curPage - 1) * this.limit });
        }
        if (!opt.limit) {
            Object.assign(opt, { limit: this.limit });
        }

        Object.assign(opt, { sort: JSON.stringify(this.gridSortField) });

        // 发送加载数据前事件
        this.fire(IBizMDControl.BEFORELOAD, opt);

        if(this.setIsOpenFilter) {
            Object.assign(opt, this.colFilterParams);
        }

        this.allChecked = false;
        this.indeterminate = false;
        this.selection = [];
        this.fire(IBizMDControl.SELECTIONCHANGE, this.selection);


        this.beginLoading();
        this.iBizHttp.post(this.getBackendUrl(), opt).subscribe(response => {
            this.endLoading();
            if (!response.items || response.ret !== 0) {
                if (response.errorMessage) {
                    this.iBizNotification.error('', response.errorMessage);
                }
                return;
            }
            this.items = this.rendererDatas(response.items);
            this.totalrow = response.totalrow;
            if(response.summaryitem) {
                this.setPinnedBottomRow(response.summaryitem);
            }
            this.fire(IBizMDControl.LOADED, response.items);
        }, error => {
            this.endLoading();
            console.log(error.info);
        });
    }

    /**
     * 表格准备完成
     *
     * @param {*} obj
     * @memberof IBizDataGridPro
     */
    public onGridReady() {
        return (params) => {
            this.agGridApi = params.api;
            this.agGridColumnApi = params.columnApi;
        };
    }

    /**
     * 排序
     *
     * @param {*} argu
     * @memberof IBizDataGrid
     */
    public elementSortChange() {
        return () => {
            var sorts:Array<any> = this.agGridApi.getSortModel();
            if(sorts.length > 0) {
                if(Object.is(sorts[0].colId, 'ag-Grid-AutoColumn')){
                    this.sort(this.autoGroupColumn.field, sorts[0].sort);
                } else {
                    this.sort(sorts[0].colId, sorts[0].sort);
                }
            }
        }
    }

    /**
     * 选中值变化
     *
     * @memberof IBizDataGrid2
     */
    public selectionChanged() {
        return () => {
            if(this.openRowEdit) {
                this.agGridApi.deselectAll();
                return;
            }
            this.selection = this.agGridApi.getSelectedRows();
            this.fire(IBizMDControl.SELECTIONCHANGE, this.selection);
        }
    }

    public isRowSelectable() {
        return () => {
            return !this.openRowEdit;
        }
    }

    /**
     * 行双击
     *
     * @returns
     * @memberof IBizDataGrid2
     */
    public rowDbClicked() {
        return (param) => {
            if(!this.openRowEdit && !Object.is(param.rowPinned, 'bottom') && !Object.is(param.rowPinned, 'top')) {
                this.fire(IBizDataGrid.ROWDBLCLICK, this.selection);
            } 
        }
    }

    /**
     * 设置是否支持多选
     * 
     * @param {boolean} state 是否支持多选
     * @memberof IBizGrid
     */
    public setMultiSelect(state: boolean): void {
        super.setMultiSelect(state);
        this.autoGroupColumn.headerCheckboxSelection = state;
        if(this.agGridApi) {
            this.agGridApi.refreshHeader();
        }
    }

    /**
     * 注册多数据列
     *
     * @memberof IBizDataGrid2
     */
    public regColumnDefs(): void {

    }

    /**
     * 注册多数据列
     *
     * @param {*} column
     * @returns
     * @memberof IBizDataGrid2
     */
    public regColumnDef(column: any) {
        if (Object.keys(column).length === 0) {
            return;
        }
        this.columnDefs.push(column);
        this.regColumn(column);
    }

    /**
     * 设置多数据列头
     * 
     * @param {*} [column={}] 
     * @returns {void} 
     * @memberof IBizMDControl
     */
    public regColumn(column: any = {}): void {
        if (Object.keys(column).length === 0) {
            return;
        }
        if (!this.columns) {
            this.columns = [];
        }
        if(Object.is(column.colType, 'GROUPGRIDCOLUMN') && column.children) {
            column.children.forEach(col => {
                this.regColumn(col);
            });
        } else {
            if(Object.is(this.getGridStyle(), 'TREEGRID') && this.treeColMode.parentText && Object.is(this.treeColMode.text, column.field)) {
                this.setAutoTreeColumn(column);                
                column.hide = true;
            } else if(column.rowGroupIndex === 1) {
                this.setAutoGroupColumn(column);
                column.hide = true;
            }
            if(column.filter) {
                this.colFilterParams[column.searchName] = '';
            }
            this.columns.push(column);
        }
    }

    /**
     * 默认展开分组层级
     * {-1: 全部展开, 0: 不展开, 1: 展开一级}
     * @returns {number}
     * @memberof IBizDataGrid2
     */
    public getGroupDefExpand(): number {
        return -1
    }

    /**
     * 分组列
     *
     * @returns
     * @memberof IBizDataGrid2
     */
    public getAutoGroupCol() {
        return this.autoGroupColumn;
    }

    /**
     * 获取树数据层级结构
     *
     * @returns
     * @memberof IBizDataGrid2
     */
    public getTreePath() {
        return (data) => {
            return data.paths;
        }
    }

    /**
     * 获取表格样式类型
     *
     * @returns {string}
     * @memberof IBizDataGrid2
     */
    public getGridStyle(): string {
        return '';
    }

    /**
     * 设置树模型
     *
     * @param {*} [column={}]
     * @memberof IBizDataGrid2
     */
    public setTreeColMode(): void {
        
    }

    /**
     * 设置自定义树列
     *
     * @param {*} [column={}]
     * @memberof IBizDataGrid2
     */
    public setAutoTreeColumn(column: any = {}): void {
        if(!this.autoGroupColumn) {
            this.autoGroupColumn = {};
        }
        Object.assign(this.autoGroupColumn, column);
        delete this.autoGroupColumn.hide;
        this.autoGroupColumn.cellRendererParams = {
            checkbox: true,
            suppressCount: true,
        }
    }

    /**
     * 设置自定义分组列
     *
     * @param {*} [column={}]
     * @memberof IBizDataGrid2
     */
    public setAutoGroupColumn(column: any = {}): void {
        if(!this.autoGroupColumn) {
            this.autoGroupColumn = {};
        }
        Object.assign(this.autoGroupColumn, column);
        delete this.autoGroupColumn.hide;
        this.autoGroupColumn.cellRendererParams = {
            checkbox: true,
            suppressCount: true,
        }
    }

    /**
     * 创建复选框列
     *
     * @memberof IBizDataGrid2
     */
    public setCheckboxColumn(): void {
        if(!this.autoGroupColumn) {
            this.autoGroupColumn = {};
        }
        Object.assign(this.autoGroupColumn, {
            width: 42,
            maxWidth: 42,
            pinned: 'left',
            field: 'srf_grid_checkbox',
            suppressMovable: true,
            suppressResize: true,
            suppressMenu: true,
            suppressSorting: true,
            suppressFilter: true,
            checkboxSelection: true,
            suppressSizeToFit: true,
            headerCheckboxSelection: true
        });
        if(this.columnDefs) {
            this.columnDefs.push(this.autoGroupColumn);
        }
    }

    /**
     * 渲染绘制多项数据
     *
     * @param {Array<any>} items
     * @returns {Array<any>}
     * @memberof IBizGrid
     */
    public rendererDatas(items: Array<any>): Array<any> {
        if(Object.is(this.getGridStyle(), 'TREEGRID') && this.treeColMode.parentId && this.treeColMode.id) {
            let arr: Array<any> = [...items];
            arr.forEach((item) => {
                item.paths = [];
                this.setTreePath(items, item, item.paths);
            });
        }
        return items;
    }

    /**
     * 设置树路径
     *
     * @param {Array<any>} items
     * @param {*} [item={}]
     * @param {Array<string>} [paths=[]]
     * @memberof IBizDataGrid2
     */
    public setTreePath(items: Array<any>, item: any = {}, paths: Array<string> = []) {
        let id = this.treeColMode.id;
        let text = this.treeColMode.text?this.treeColMode.text: 'srfmajortext';
        let parentId = this.treeColMode.parentId;
        let parentText = this.treeColMode.parentText;
        
        if(item[parentId] && !Object.is(item[parentId], '')) {
            let hesParent: boolean = true;
            items.forEach((data) => {
                if(Object.is(data[id], item[parentId])) {
                    this.setTreePath(items, data, paths);
                    hesParent = false;
                }
            })
            if(hesParent && parentText) {
                let index = items.indexOf(item);
                let data: any = {};
                data[id] = item[parentId];
                data[text] = item[parentText];
                data.paths = [item[parentText]];
                items.splice(index, 0 ,data);
                paths.push(item[parentText]);
            }
        }
        paths.push(item[text]);
    }

    /**
     * 是否开启行编辑
     *
     * @returns {boolean}
     * @memberof IBizDataGrid2
     */
    public getIsOpenEdit() {
        return (param) => {
            return (this.openRowEdit && param.node && !param.node.rowPinned);
        }
    }

    /**
     * 启用行编辑
     *
     * @param {*} params
     * @returns {void}
     * @memberof IBizDataGrid
     */
    public openEdit(params: any): void {
        if (!this.isEnableRowEdit) {
            this.iBizNotification.info('提示', '未启用行编辑');
            return;
        }
        this.agGridApi.deselectAll();
        if (!this.openRowEdit) {
            this.openRowEdit = true;
            this.items.forEach((item: any) => { item.openeditrow = true; });
            this.backupDatas = [...JSON.parse(JSON.stringify(this.items))];
            this.items.forEach((item: any, index: number) => {
                this.setEditItemState(item.srfkey);
                this.editRow(item, index, false);
            });
        }
    }

    /**
     * 行编辑单元格值变化
     *
     * @param {string} name
     * @param {*} data
     * @memberof IBizGrid
     */
    public colValueChange(name: string, value: string, data: any): void {
        const srfkey = data.srfkey;
        const _data = this.items.find(back => Object.is(back.srfkey, srfkey));
        if (this.state[srfkey] && this.state[srfkey][name]) {
            data[name] = value;
            this.fire(IBizDataGrid.UPDATEGRIDITEMCHANGE, { name: name, data: data });
        }
    }

    /**
     * 获取语言资源
     *
     * @returns {*}
     * @memberof IBizDataGrid2
     */
    public getLocaleText(): any {
        return IBizDataGrid2.LOCALETEXT;
    }

    /**
     * 设置是否开启列过滤
     *
     * @memberof IBizDataGrid2
     */
    public setIsOpenFilter(): void {

    }

    /**
     * 获取列过滤字段值
     *
     * @param {*} param
     * @returns {*}
     * @memberof IBizDataGrid2
     */
    public getColFilterValue(param): any {
        if(!param) {
            return;
        }
        let filterModel: any = this.agGridApi.getFilterModel();
        let defCol: any = param.colDef;
        if(defCol && filterModel[defCol.field]) {
            return filterModel[defCol.field].filter;
        }
        return '';

    }

    /**
     * 过滤值改变
     *
     * @returns
     * @memberof IBizDataGrid2
     */
    public filterChanged() {
        return () => {
            let filterModel: any = this.agGridApi.getFilterModel();
            let keys: Array<string>  = Object.keys(this.colFilterParams);
            let isChange: boolean = false;
            keys.forEach((key) => {
                if(filterModel) {
                    let index = this.columns.findIndex((column) => Object.is(column.searchName, key));
                    let column: any = this.columns[index];
                    if(filterModel.hasOwnProperty(column.field)) {
                        if(Object.is(this.colFilterParams[key], filterModel[column.field].filter)) {
                            return;
                        } else {
                            this.colFilterParams[key] = filterModel[column.field].filter;
                            isChange = true;
                        }
                    } else if (Object.is(this.colFilterParams[key], '')) {
                        return;
                    } else {
                        this.colFilterParams[key] = '';
                        isChange = true;
                    }
                } else if (Object.is(this.colFilterParams[key], '')){
                    return;
                } else {
                    this.colFilterParams[key] = '';
                    isChange = true;
                }
            });
            if(isChange) {
                this.refresh();
            }
        }
    }

    /**
     * 获取预置组件
     *
     * @returns
     * @memberof IBizDataGrid2
     */
    public getFrameworkComponents() {
        return {
            customTextColumnFilter: Vue.options.components['costom-text-column-filter'],
            customSelectColumnFilter: Vue.options.components['costom-select-column-filter'],
        }
    }

    /**
     * 获取列默认设置
     *
     * @returns
     * @memberof IBizDataGrid2
     */
    public getDefColOption() {
        return {
            menuTabs: ['generalMenuTab', 'columnsMenuTab'],
            pinnedRowCellRenderer: (data) => {
            	return this.getPinnedRowCellRender(data);
            }
        }
    }

    /**
     * 设置底部固定行
     *
     * @param {*} item
     * @memberof IBizDataGrid2
     */
    public setPinnedBottomRow(item: any): void {
        if(item) {
            if(Array.isArray(item)) {
                this.agGridApi.setPinnedBottomRowData(item);
            } else {
                this.agGridApi.setPinnedBottomRowData([item]);
            }
        }
    }

    /**
     * 获取固定行列绘制
     *
     * @param {*} data
     * @returns {string}
     * @memberof IBizDataGrid2
     */
    public getPinnedRowCellRender(data: any): string {
        return data.value;
    }

    /**
     * 表格模型变化
     *
     * @memberof IBizDataGrid2
     */
    public onGridModelChange() {
        let subject: any = new rxjs.Subject();
        subject.pipe(rxjs.operators.debounceTime(2000)).subscribe(() => {
            this.setModel(this.agGridColumnApi.getColumnState());
        });
        return () => {
            subject.next();
        }
    }

    /**
     * 多语言设置
     *
     * @static
     * @memberof IBizDataGrid2
     */
    public static LOCALETEXT = {
        pinColumn: '锁定列',
        autosizeThiscolumn: '自动调整此列的大小',
        autosizeAllColumns: '自动调整所有列的大小',
        resetColumns: '重置所有列',
        pinLeft: '锁定左侧',
        pinRight: '锁定右侧',
        noPin: '不锁定',
        noRowsToShow: '暂无数据'
    }
}